<html>
    <head>
        <title>程序化的事件监听器</title>
    </head>
    <body>
        <script>
        // 程序化的事件监听器
                /*
                    现在，你已经知道了 $emit 的用法，它可以被 v-on 指令监听，但是Vue实例同时在其事件接口中提供了其他方法。
                    我们可以：

                        1、通过 $on(eventName,eventHandler) 监听一事件
                        2、通过 $once(eventName,eventHandler) 一次性地监听一个事件
                        3、通过 $off(eventName,eventHandler)  移除一个事件监听器

                    你通常不会用到这些，但是当你需要在一个组件实例上手动监听事件时，它们是派得上用场的。
                    它们也可以用于代码组织工具。
                */
                // 例如，你可能经常看到这种集成一个第三方库的模式：
                         mounted:function(){
                            // Pikaday 是一个第三方日期选择器的库
                            this.picker =new Pikaday({
                                field: this.$refs.input, // 挂在到哪个元素上
                                format:'YYYY-MM-DD'      // 值的格式化方式 
                            })
                         },
                         // 组件被销毁之前，也销毁这个日期选择器实例
                         beforeDestroy:function(){
                            this.picker.destroy();
                         }

                /*
                    这里有两个潜在问题：
                         1、它需要在这个组件实例中保存这个 picker 实例，如果可以的话最好只有生命周期钩子可以访问到它。
                                 这并不算严重的问题，但是它可以被视为杂物。

                         2、我们的建立代码独立于我们的清理代码，这使得我们比较难于程序化地清理我们建立的所有东西。
                */
                // 你应该通过一个程序化的监听器解决这两个问题:
                         mounted:function(){
                            var picker = new Pickaday({
                                field:this.$refs.input,
                                format:'YYYY-MM-DD'
                            });

                            this.$once('hook:beforeDestory',function(){
                                picker.destroy();
                            });
                         }

                /*
                    使用了这个策略，我甚至可以让多个输入框元素同时使用不同的Pickaday实例，每个新的实例都程序化地在后期清理它自己：
                */
                         mounted:function(){
                            this.attachDatepicker('startDateInput'); 
                            this.attachDatepicker('endDateInput');
                         },
                         methods:{
                            // 挂载pickaday实例到指定元素上
                            attachDatepicker:function(refName){
                                var picker= new Pickaday({
                                    field:this.$refs[refName],
                                    format:'YYYY-MM-DD'
                                });

                                this.$once('hook:beforeDestory',function(){
                                    picker.destroy();
                                })
                            }

                         }

                /*
                    官网教程与本处对应的位置有这个例子的完整代码链接。

                    注意：
                         即便如此，如果你发现自己不得不在单个组件里做很多建立和清理的工作，最好的方式通常还是创建等多的模块化组件。

                    想了解更多邓旭华监听器的内容，请查阅 "实例方法/事件"相关的API
                */

                /*
                    注意：
                         Vue的事件系统不同于浏览器的 "EventTarget API"。
                         尽管他们工作起来是相似的，但是 $emit $on  $off 并不是 dispatchEvent、addEventListener 和 removeEventListener 的别名。
                */

        </script>
    </body>
</html>